package com.wc.算法基础课.D第四讲数学知识.高斯消元.高斯消元解线性方程组;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.StringTokenizer;

/**
 * @Author congge
 * @Date 2024/1/23 16:36
 * @description 高斯消元解线性方程组
 * https://www.acwing.com/problem/content/885/
 */
public class Main {
    /**
     * 线性代数
     * 1、 找出列最大的值变成 1, 并且交换到上面，然后将该列所有的其他行变为 0
     * 2、 其次按照上述，直到遍历到最后一列
     * 3、 判断是否为无穷多个解，无解，或者是唯一解
     * 4、 将上面的从上到下减到最后一行，将除去自己的位置，都变成 0
     * 5、 最后一列就是解
     */

    static FastReader sc = new FastReader();
    static PrintWriter out = new PrintWriter(System.out);
    static int N = 110;
    static double[][] a = new double[N][N];
    static int n;
    // double是有误差的, 所以我们认为绝对值小于eps的值为0
    static double eps = 1e-12;

    public static void main(String[] args) {
        n = sc.nextInt();
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n + 1; j++) {
                a[i][j] = sc.nextDouble();
            }
        }
        int res = gauss();
        if (res == 0) {
            for (int i = 0; i < n; i++) {
                if (Math.abs(a[i][n]) < eps)
                    a[i][n] = 0;
                out.printf("%.2f\n", a[i][n]);
            }
        } else if (res == 1) {
            out.println("Infinite group solutions");
        } else {
            out.println("No solution");
        }
        out.flush();
    }

    /**
     * @return 0 代表唯一解
     * 1 代表无穷多个解
     * 2 代表无解
     */
    static int gauss() {
        // 当前列，当前行
        int c, r;
        for (c = 0, r = 0; c < n; c++) {
            // 最大的行
            int t = c;
            for (int i = c + 1; i < n; i++) {
                if (Math.abs(a[i][c]) > Math.abs(a[t][c])) {
                    t = i;
                }
            }
            // 最大的都是0,那就都是0了，不需要下一步了
            if (Math.abs(a[t][c]) < eps) continue;

            // 交换
            swap(a, t, r);

            // 开始将自己变成 1
            for (int i = n; i >= c; i--) a[r][i] /= a[r][c];

            // 将其他行的该列变为0，r行
            for (int i = r + 1; i < n; i++) {
                for (int j = n; j >= c; j--) {
                    a[i][j] -= a[i][c] * a[r][j];
                }
            }
//            show();
            r++;
        }
        // 检查r < n 要么无解，要么有无数个解
        if (r < n) {
            // 检查r ~ n是不是尾部都是0, 如果不是,就无解
            for (int i = r; i < n; i++) {
                if (Math.abs(a[i][n]) > eps) return 2;
            }
            return 1;
        }

        // 解出这个唯一解,只是更改了最后一列
        for (int i = n - 1; i >= 0; i--) {
            for (int j = i + 1; j < n; j++) {
                a[i][n] -= a[j][n] * a[i][j];
            }
        }
//        show();
        // 如果我们需要改所有的列的话,
//        for (int i = n - 1; i > 0; i--) {
//            for (int j = 0; j < i; j++) {
//                a[j][n] -= a[j][i] * a[i][n];
//                a[j][i] = 0;
//            }
//            show();
//        }


        return 0;
    }

    static void show() {
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n + 1; j++) {
                out.printf("%.2f ", a[i][j]);
            }
            out.println();
        }
        out.println();
        out.flush();
    }

    static void swap(double[][] a, int i, int j) {
        double[] tmp = a[i];
        a[i] = a[j];
        a[j] = tmp;
    }
}

class FastReader {
    StringTokenizer st;
    BufferedReader br;

    FastReader() {
        br = new BufferedReader(new InputStreamReader(System.in));
    }

    String next() {
        while (st == null || !st.hasMoreElements()) {
            try {
                st = new StringTokenizer(br.readLine());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return st.nextToken();
    }

    int nextInt() {
        return Integer.parseInt(next());
    }

    String nextLine() {
        String s = "";
        try {
            s = br.readLine();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return s;
    }

    long nextLong() {
        return Long.parseLong(next());
    }

    double nextDouble() {
        return Double.parseDouble(next());
    }

    // 是否由下一个
    boolean hasNext() {
        while (st == null || !st.hasMoreTokens()) {
            try {
                String line = br.readLine();
                if (line == null)
                    return false;
                st = new StringTokenizer(line);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return true;
    }
}